package com.example.zxx.springboot3.util;

import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.*;

/**
 * Kif:if工具类<br/>
 * 参考 Optional类
 *
 * @author zhangxiaoxiang
 * @date 2022年2月1日
 */
public interface Kif {
    /**
     * 构造方法
     */
    Kif B = new Kif() {
    };

    /**
     * 满足条件直接抛异常
     *
     * @param rule 条件判断
     * @param re   异常类型
     * @param <RE> 异常
     */
    default <RE extends RuntimeException> void ifThenRe(boolean rule, RE re) {
        // throwOf(rule, (Consumer<RuntimeException>) e -> {}, re);
        if (rule) {
            throw re;
        }
    }

    /**
     * 满足条件就直接抛异常
     *
     * @param rule      规则
     * @param elseThrow 不满足条件抛异常
     * @param <E>       异常
     * @throws E 抛异常
     */
    default <E extends Throwable> void ifThenSuRe(boolean rule, Supplier<? extends E> elseThrow) throws E {
        if (rule) {
            throw elseThrow.get();
        }
    }

    /**
     * 满足条件先执行逻辑再抛异常
     *
     * @param rule   判断规则
     * @param before 判断规则后执行的逻辑
     * @param re     异常类型
     * @param <RE>   异常
     */
    default <RE extends RuntimeException> void ifThenRe(boolean rule, Consumer<RE> before, RE re) {
        if (rule) {
            before.accept(re);
            throw re;
        }
    }

    /**
     * 满足条件执行,否则抛异常[这里为了避免模棱两可的重载,所以另起一个方法名称]
     *
     * @param rule      判断规则
     * @param t         请求参数
     * @param consumer  满足条件执行力逻辑
     * @param elseThrow 抛异常
     * @param <T>       请求参数类型
     * @param <E>       异常类型
     * @throws E 异常
     */
    default <T, E extends RuntimeException> void ifThenSuRe(boolean rule, T t, Consumer<? super T> consumer, Supplier<? extends E> elseThrow) throws E {
        if (rule) {
            consumer.accept(t);
        } else {
            throw elseThrow.get();
        }
    }

    /**
     * 满足条件先执行逻辑再抛异常[Supplier形]
     *
     * @param param    请求参数
     * @param rule     判断条件
     * @param function 执行逻辑
     * @param re       异常
     * @param <RE>     异常类型
     * @param <P>      请求参数类型
     * @param <R>      返回类型
     * @return 返回值
     * @throws RE 异常类型
     */
    default <RE extends RuntimeException, P, R> R ifThenSuRe(P param, Predicate<? super P> rule, Function<? super P, ? extends R> function, Supplier<? extends RE> re) throws RE {
        if (rule.test(param)) {
            return function.apply(param);
        }
        throw re.get();
    }

    /**
     * 满足条件先执行逻辑再抛异常
     *
     * @param param    请求参数
     * @param rule     判断条件
     * @param function 执行逻辑
     * @param re       异常
     * @param <RE>     异常类型
     * @param <P>      请求参数类型
     * @param <R>      返回类型
     * @return 返回值
     * @throws RE 异常类型
     */
    default <RE extends RuntimeException, P, R> R ifThenRe(P param, Predicate<? super P> rule, Function<? super P, ? extends R> function, RE re) throws RE {
        if (rule.test(param)) {
            return function.apply(param);
        }
        throw re;
    }

    /**
     * 满足条件执行逻辑,不满足直接抛异常[返回值和请求参数无关]
     *
     * @param param     请求参数
     * @param rule      if规则
     * @param then      执行if规则逻辑
     * @param elseThrow 不满足抛异常
     * @param <E>       异常
     * @param <P>       请求参数
     * @param <RES>     返回参数类型
     * @return 返回值
     * @throws E 异常
     */
    default <E extends Throwable, P, RES> RES ifThenThr(P param, Predicate<? super P> rule, Supplier<RES> then, Supplier<? extends E> elseThrow) throws E {
        if (rule.test(param)) {
            return then.get();
        }
        throw elseThrow.get();
    }


    /**
     * 满足条件,执行相应逻辑
     *
     * @param b        判断条件
     * @param param    请求参数
     * @param consumer 满足条件执行业务代码[查数据库,缓存,记录日志,抛异常等等]
     * @param <P>      请求参数类型
     */
    default <P> void ifThen(boolean b, P param, Consumer<? super P> consumer) {
        if (b) {
            consumer.accept(param);
        }
    }

    /**
     * [不带返回值]请求参数满足条件执行逻辑,不满足执行另一个逻辑
     *
     * @param param  请求参数
     * @param rule   判断规则
     * @param then   满足条件执行逻辑,
     * @param orElse 不满足执行另一个逻辑
     * @param <P>    请求参数类型
     */
    default <P> void ifThen(P param, Predicate<? super P> rule, Consumer<? super P> then, Consumer<? super P> orElse) {
        if (rule.test(param)) {
            then.accept(param);
        } else {
            orElse.accept(param);
        }
    }

    /**
     * [不带返回值]满足条件执行,否则执行另一个逻辑Runnable
     *
     * @param rule     判断规则
     * @param runnable 满足条件执行
     * @param orElse   否则执行另一个逻辑Runnable
     */
    default void ifThen(boolean rule, Runnable runnable, Runnable orElse) {
        if (rule) {
            runnable.run();
        } else {
            orElse.run();
        }
    }

    /**
     * 满足条件执行逻辑,不满足执行另一个逻辑
     *
     * @param b        判断条件
     * @param param    请求参数
     * @param consumer 满足条件执行逻辑
     * @param then     不满足执行另一个逻辑
     * @param <P>      请求参数类型
     */
    default <P> void ifThen(boolean b, P param, Consumer<? super P> consumer, Consumer<? super P> then) {
        if (b) {
            consumer.accept(param);
        } else {
            then.accept(param);
        }
    }

    /**
     * 满足if条件,执行相应逻辑
     *
     * @param b        判断规则
     * @param runnable 相应逻辑
     */
    default void ifThen(boolean b, Runnable runnable) {
        if (b) {
            runnable.run();
        }
    }

    /**
     * 满足条件,执行相应逻辑
     *
     * @param rule  判断条件
     * @param param 请求参数
     * @param then  满足条件执行业务代码[查数据库,缓存,记录日志,抛异常等等]
     * @param <P>   请求参数类型
     */
    default <P> void ifThen(P param, Predicate<? super P> rule, Consumer<? super P> then) {
        if (rule.test(param)) {
            then.accept(param);
        }
    }

    /**
     * ifFilter 链式if[如果需简化请求参数 param 的传递,参考Optional<T>类,这里是默认方法,所以没有实现这种操作 ]
     *
     * @param param 请求参数
     * @param rule  判断条件
     * @param then  执行逻辑
     * @param <P>   返回类型
     * @return 返回值 Kif
     */
    default <P> Kif ifFilter(P param, Predicate<? super P> rule, Consumer<? super P> then) {
        if (rule.test(param)) {
            then.accept(param);
        }
        return this;
    }

    /**
     * [带返回]满足条件,返回参数,否则抛异常
     *
     * @param rule     判断条件
     * @param param    请求参数
     * @param function function函数
     * @param re       异常
     * @param <RE>     异常类型
     * @param <P>      请求参数类型
     * @param <RES>    返回值类型
     * @return 返回值
     */
    default <RE extends RuntimeException, P, RES> RES ifResOrElseRe(boolean rule, P param, Function<? super P, ? extends RES> function, RE re) {
        if (rule) {
            return function.apply(param);
        }
        throw re;
    }

    /**
     * [带返回]满足条件,返回参数-Function形if/else
     *
     * @param rule     判断条件
     * @param param    请求参数
     * @param function 满足if逻辑
     * @param orElse   满足else逻辑
     * @param <P>      请求参数类型
     * @param <RES>    返回参数类型
     * @return 返回值
     */
    default <P, RES> RES ifResOrElseRes(boolean rule, P param, Function<? super P, ? extends RES> function, Function<P, RES> orElse) {
        return rule ? function.apply(param) : orElse.apply(param);
    }

    /**
     * [带返回值]满足条件,返回参数-Supplier形if/else
     * 处理典型的if else类型 </p>
     * 三目运算return rule ? then.get() : orElse.get();
     *
     * @param rule     判断条件
     * @param supplier 满足条件执行逻辑,返回值
     * @param orElse   不满足执行另一个逻辑,返回值
     * @param <RES>    返回值类型
     * @return 返回值
     */
    default <RES> RES ifResOrElseRes(boolean rule, Supplier<RES> supplier, Supplier<RES> orElse) {
        return rule ? supplier.get() : orElse.get();
    }

    /**
     * [带返回值]满足条件,返回参数-Supplier形if/else
     *
     * @param rule   判断规则
     * @param param  请求参数
     * @param then   满足if规则执行逻辑返回值
     * @param orElse orElse执行逻辑返回值
     * @param <P>    请求参数类型
     * @param <R>    返回参数类型
     * @return 返回值
     */
    default <P, R> R ifResOrElseRes(Predicate<? super P> rule, P param, Supplier<? extends R> then, Supplier<? extends R> orElse) {
        return rule.test(param) ? then.get() : orElse.get();
    }


    /**
     * [带返回]满足条件,返回参数(未匹配返回null) </p>
     *
     * @param param 请求参数
     * @param rule  判断规则
     * @param then  业务逻辑
     * @param <P>   请求参数类型
     * @param <RES> 返回值类型
     * @return 返回值
     */
    default <P, RES> RES ifResOrElseNull(P param, Predicate<? super P> rule, Function<? super P, ? extends RES> then) {
        return rule.test(param) ? then.apply(param) : null;
    }

    /**
     * 嵌套if,返回对应的匹配值,未匹配返回null,类比Optional的.filter()链式调用
     *
     * @param param       请求参数
     * @param map         map请求参数
     * @param defaultThen 未匹配默认返回值(Function函数)
     * @param <P>         请求参数类型
     * @param <RES>       返回值类型
     * @return 返回值
     */
    default <P, RES> RES nestedIfRse(P param, Map<Predicate<? super P>, Function<? super P, ? extends RES>> map, Function<P, RES> defaultThen) {
        for (Map.Entry<Predicate<? super P>, Function<? super P, ? extends RES>> entry : map.entrySet()) {
            //每个if 匹配的结果
            return ifResOrElseNull(param, p -> entry.getKey().test(param), p -> null);
        }
        //if 没有匹配默认返回的null
        return Objects.nonNull(defaultThen) ? defaultThen.apply(param) : null;
    }

    /**
     * 嵌套if,返回对应的匹配值,未匹配返回null,类比Optional的.filter()链式调用
     *
     * @param param       请求参数
     * @param map         map请求参数
     * @param defaultThen 未匹配默认返回值(Supplier函数)
     * @param <P>         请求参数类型
     * @param <RES>       返回值类型
     * @return 返回值
     */
    default <P, RES> RES nestedIfRseSu(P param, Map<Predicate<? super P>, Function<? super P, ? extends RES>> map, Supplier<RES> defaultThen) {
        for (Map.Entry<Predicate<? super P>, Function<? super P, ? extends RES>> entry : map.entrySet()) {
            return ifResOrElseNull(param, p -> entry.getKey().test(param), p -> null);
        }
        return Objects.nonNull(defaultThen) ? defaultThen.get() : null;
    }

    /**
     * 嵌套if,返回对应的匹配值[if分支或者map得key未匹配抛异常]
     *
     * @param param 请求参数
     * @param map   map请求参数
     * @param re    未匹配抛异常
     * @param <P>   请求参数类型
     * @param <RES> 返回值类型
     * @param <RE>  异常类型
     * @return 返回值
     */
    default <P, RES, RE extends RuntimeException> RES nestedIfValueRe(P param, Map<Predicate<? super P>, Function<? super P, ? extends RES>> map, RE re) {
        for (Map.Entry<Predicate<? super P>, Function<? super P, ? extends RES>> entry : map.entrySet()) {
            //未匹配if分支抛异常形式
            return ifResOrElseRe(entry.getKey().test(param), param, map.get(entry.getKey()), re);
        }
        //未匹配map的key抛异常的形式
        throw re;
    }

    /**
     * 嵌套if型执行逻辑,无返回值(Consumer形式),类比Optional的.filter()链式调用
     *
     * @param param 请求参数[不用太在意参数类型,内部用到的交给Consumer,没有的在前面的逻辑代码去找]
     * @param map   嵌套if转成的map
     * @param <P>   请求参数类型
     */
    default <P> void nestedIfVoid(P param, Map<Predicate<? super P>, Consumer<? super P>> map) {
        doNestedIf(param, map);
    }

    /**
     * 嵌套if型执行逻辑,无返回值(Consumer形式),默认匹配执行
     *
     * @param param       请求参数
     * @param map         嵌套if转成的map
     * @param defaultThen 默认逻辑
     * @param <P>         请求参数类型
     */
    default <P> void nestedIfVoid(P param, Map<Predicate<? super P>, Consumer<? super P>> map, Consumer<? super P> defaultThen) {
        doNestedIf(param, map);
        defaultThen.accept(param);
    }

    /**
     * doNestedIf 处理内部逻辑
     *
     * @param param 请求参数
     * @param map   if转换成的map
     * @param <P>   请求参数类型
     */
    private <P> void doNestedIf(P param, Map<Predicate<? super P>, Consumer<? super P>> map) {
        for (Map.Entry<Predicate<? super P>, Consumer<? super P>> entry : map.entrySet()) {
            if (entry.getKey().test(param)) {
                entry.getValue().accept(param);
                return;
            }
        }
    }

    /**
     * [待优化]创建map处理[这里可以改造成链式调用的map]
     *
     * @param <P> 请求参数类型
     * @return Map
     */
    default <P> Map<Predicate<? super P>, Consumer<? super P>> buildMap() {
        return new HashMap<>(16);
    }

    /**
     * [待优化]创建含有返回值的map处理[这里可以改造成链式调用的map]
     *
     * @param <P>   请求参数类型
     * @param <RES> 返回参数类型
     * @return 返回值
     */
    default <P, RES> Map<Predicate<? super P>, Function<? super P, ? super RES>> buildResMap() {
        return new HashMap<>(16);
    }


//    ------------------------------------其他---------------------------

    /**
     * Assert自定义断言信息
     *
     * @param b       判断条件
     * @param message 自定义断言异常信息
     */
    default void ifThenAssert(boolean b, String message) {
        Assert.isTrue(b, message);
    }

    /**
     * 如果存在值，则使用该值执行给定的操作，否则执行给定的基于空的操作-JDK11
     *
     * @param param       请求参数
     * @param rule        判断规则
     * @param action      操作
     * @param emptyAction 为空的操作
     * @param <P>         请求参数类型
     */
    default <P> void ifPresentOrElse(P param, Predicate<? super P> rule, Consumer<? super P> action, Runnable emptyAction) {
        if (rule.test(param)) {
            action.accept(param);
        } else {
            emptyAction.run();
        }
    }

    /**
     * if分支[可以再简化,这里是为了满足某些需求]
     * {@link Optional#ifPresentOrElse(Consumer, Runnable)}}
     *
     * @param rule        判断规则
     * @param p           请求参数
     * @param u           请求参数
     * @param function    函数
     * @param emptyAction 不满足执行逻辑
     * @param <P>         请求参数类型
     * @param <U>         请求参数类型
     * @param <RES>       返回参数类型
     * @return 返回值
     */
    default <P, U, RES> RES ifPresentOrElse(boolean rule, P p, U u, BiFunction<? super P, ? super U, RES> function, Runnable emptyAction) {
        if (rule) {
            function.apply(p, u);
        } else {
            emptyAction.run();
        }
        return null;
    }

}